#include "system.h"
#include "bsp.h"
#include "drv_key.h"


/* BootLoader */

/* static var */

#define APP_ADDR    0x90000000


/*
   ___            __  __                __       
  / _ )___  ___  / /_/ /  ___  ___ ____/ /__ ____
 / _  / _ \/ _ \/ __/ /__/ _ \/ _ `/ _  / -_) __/
/____/\___/\___/\__/____/\___/\_,_/\_,_/\__/_/   

*/
const char *boot_logo_tbl[] = 
{
    "   ___            __  __                __       ",
    "  / _ )___  ___  / /_/ /  ___  ___ ____/ /__ ____",
    " / _  / _ \\/ _ \\/ __/ /__/ _ \\/ _ `/ _  / -_) __/",
    "/____/\\___/\\___/\\__/____/\\___/\\_,_/\\_,_/\\__/_/   ",
};


/* static func */



static void boot_print_logo(void)
{
    uint8_t i = 0;

	printf("\r\n");
	printf("\x1b[34m%s\x1b[0m\r\n", boot_logo_tbl[i++]);
	printf("\x1b[34m%s\x1b[0m\r\n", boot_logo_tbl[i++]);
	printf("\x1b[34m%s\x1b[0m\r\n", boot_logo_tbl[i++]);
	printf("\x1b[34m%s\x1b[0m\r\n", boot_logo_tbl[i++]);
    printf("Powered by AWalker-H750.");
	printf("\r\n");
}

/* export func */

void boot_handle(void)
{
    int i;
    uint32_t tmp;
    void (*app_jump)(void);
    __IO uint32_t app_addr = APP_ADDR;

    /* 按键检测,key0和key1同时按下强制进入boot */
    i = 0;
    i |= drv_key_pres_key0();
    i |= drv_key_pres_key1();
    if (i)
    {
        boot_print_logo();
        return ;
    }

    /* APP栈顶检测 */
    memcpy(&tmp, (uint32_t*)APP_ADDR, sizeof(uint32_t));
    if (!(  ((tmp&0x3FF00000) == 0x20000000) ||
            ((tmp&0x3FF00000) == 0x24000000) ||
            ((tmp&0x3FF00000) == 0x30000000) ) )
    {
        boot_print_logo();
        printf("XIP head: 0x%08X\r\n", tmp);
        return ; //非法栈顶,退出
    }

    /* 关闭全局中断、时钟恢复默认状态、关闭滴答时钟 */
    system_int_disable();
    HAL_RCC_DeInit();
    SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL = 0;
    for (i=0; i<8; i++) //关闭所有中断,清除所有中断挂起标志
    {
        NVIC->ICER[i]=0xFFFFFFFF;
        NVIC->ICPR[i]=0xFFFFFFFF;
    }

    /* 使能全局中断 */
    system_int_enable();

    /* 跳转 */
    app_jump = (void (*)(void))(*((uint32_t*) (app_addr + 4))); //地址设置
    __set_MSP(*(uint32_t*)app_addr);    //设置主堆栈指针
    __set_CONTROL(0);   //设置为特权级模式,使用MSP指针
    app_jump(); //跳转

    /* 跳转成功不会执行以下代码 */
    bsp_init();
    boot_print_logo();
}


